from django.contrib.auth import get_user_model
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin, UpdateModelMixin
from rest_framework.response import Response
from rest_framework.viewsets import GenericViewSet
from django.db.models import Q
from django.contrib.auth import login
from django.urls import NoReverseMatch, reverse
from django.http import JsonResponse
from django.contrib.auth.hashers import check_password, make_password
from backend.cews.services import emailService as EmailService

from utils.decorators import required_superuser,error_response, request_data
from .serializers import UserSerializer, UserSearchSerializer
from utils.pagination import PageLimitOffsetPagination
from pydantic import ValidationError

User = get_user_model()


class UserViewSet(RetrieveModelMixin, ListModelMixin, UpdateModelMixin, GenericViewSet):
    
    serializer_class = UserSerializer
    queryset = User.objects.all()
    lookup_field = "username"
    pagination_class = PageLimitOffsetPagination

    def get_queryset(self, *args, **kwargs):
        assert isinstance(self.request.user.id, int)
        return self.queryset.filter(id=self.request.user.id)

    @action(detail=False)
    def me(self, request):
        serializer = UserSerializer(request.user, context={"request": request})
        return Response(status=status.HTTP_200_OK, data=serializer.data)
    
    @action(detail=False, methods=['post'])
    def login(self,request):
        res = login(request)
        # Check if the user is authenticated
        if request.user.is_authenticated:
            return Response({'code':1,'message': 'Successfully logged in to admin site'})
        else:
            return Response({'code':0,'message': 'Failed to log in to admin site'})

    @action(methods=['POST'],detail=False,url_name='getUserAdminUrl',url_path='getUserAdminUrl')
    def getUserAdminUrl(self, request, *args, **kwargs):
        try:
            url = reverse('admin:users_user_change',args=[request.user.pk])
        except NoReverseMatch as ex:
            return JsonResponse(status=500,data={
                'code':0,
                'message':str(ex)
            })
        return JsonResponse(status=200,data={
                'code':1,
                'url':url
            })
    
    @action(methods=['POST'],detail=False,url_name='getAdminUrl',url_path='getAdminUrl')
    @required_superuser()
    def getAdminUrl(self, request, *args, **kwargs):
        try:
            url = reverse('admin:index')
        except NoReverseMatch as ex:
            return JsonResponse(status=500,data={
                'code':0,
                'message':str(ex)
            })
        return JsonResponse(status=200,data={
                'code':1,
                'url':url
            })
    
    @request_data(
        keys=["old_password", "new_password", "confirm_new_password"],
    )
    @error_response()
    @action(methods=['POST'],detail=False,url_name='changepassword',url_path='changepassword')
    def changepassword(self, request, old_password, new_password, confirm_new_password):
        print(old_password)
        print(new_password)
        print(confirm_new_password)

        user = self.queryset.get(pk=request.user.id)

        is_correct = check_password(old_password, user.password)

        if is_correct:
            new_hash_pw = make_password(new_password)
            user.password = new_hash_pw
            user.save()

            return JsonResponse(status=200,data={
                'code':1,
                'message': 'Change password successful'
            })
        
        else:
            return JsonResponse(status=200,data={
                'code':0,
                'message': 'Incorrect old password'
            })
    
    
    @request_data(
        keys=["username", "email"],
    )
    @error_response()
    @action(methods=['POST'],detail=False,url_name='search_user_email',url_path='search_user_email')
    def search_user_email(self, request, username, email):
        query = Q()
        if username:
            query &= Q(username__icontains=username)
        if email:
            query &= Q(email__icontains=email)
        user = request.user
        queryset = self.queryset.filter(query).exclude(id=user.id)
        paginator  = self.pagination_class()
        try:
            result = paginator.paginate_queryset(queryset, request) 
        except ValidationError as e:
            error_info = e.errors()
            ctx = error_info[0]['ctx']
            ctx_error = ctx["error"]
            return Response(status=400, data=str(ctx_error))
        ser = UserSearchSerializer(result, many=True)
        return paginator.get_paginated_response(ser.data)


    # @request_data(
    #     keys=["user_id"],
    # )
    # @error_response()
    # @action(methods=['POST'],detail=False,url_name='test_send_email',url_path='test_send_email')
    # def test_send_email(self, request, user_id):
    #     EmailService.send_email("feng@gnstec.com.hk", "sub_xxxx", "邮件内容")
    #     return Response(status=200, data={
    #         'code':1,
    #         'message': 'Send email to owner after endorsed successful'
    #     })
